﻿#define DEBUG

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace AzaEngine
{
    public class File
    {
        private string filename;
        public string FilenameFull { get; set; }
        public string Filename { get { return filename; } }
        public string NewFilename { get; set; }     // Novo nome que terá o arquivo quando for renomeado
        private bool FileRenamed;

        public string Extension
        {
            get
            {
                return Path.GetExtension(FilenameFull);
            }
        }

        public string Directory
        {
            get
            {
                return Path.GetDirectoryName(FilenameFull);
            }
        }

        public string NewFilenameFull
        {
            get
            {
                return Directory + @"\" + NewFilename + Extension;
            }
        }

        public File(string filename)
        {
            SetFilename(filename);
        }

        public File(string filename, string newFilename)
        {
            SetFilename(filename);
            NewFilename = newFilename;
        }

        public void SetFilename(string filename)
        {
            FilenameFull = filename;
            this.filename = Path.GetFileNameWithoutExtension(filename);
            NewFilename = String.Empty;
        }

        public bool ChangedName()
        {
            return Filename != NewFilename && NewFilename != string.Empty;
        }

        public void ApplyRename()
        {
            SetFilename(NewFilename);
            FileRenamed = true;
        }

        public bool Renamed()
        {
            return FileRenamed;
        }

    }

    public class Folder
    {
        public int Deep { get; set; }
        private string foldername;
        public string FolderNameFull { get; set; }
        public string FolderName { get { return foldername; } }
        public string NewFolderName { get; set; }

        public string Directory { get; set; }
        public bool Root { get; set; }
        public List<File> Files = new List<File>();
        private bool folderRenamed;

        public string NewFolderNameFull
        {
            get
            {
                return Directory + '\\' + NewFolderName;
            }
        }

        public Folder() { }

        public Folder(string foldername)
        {
            SetFolderName(foldername);
            Root = false;
        }
        public Folder(string foldername, bool root)
        {
            SetFolderName(foldername);
            Root = root;
        }

        public Folder(string foldername, string newFilename)
        {
            NewFolderName = newFilename;
            SetFolderName(foldername);
            Root = false;
        }

        private void SetFolderName(string foldername)
        {
            FolderNameFull = foldername;
            NewFolderName = string.Empty;

            // Folder Full Name
            if (FolderNameFull[FolderNameFull.Length - 1] == '\\')
            {
                FolderNameFull = FolderNameFull.Substring(0, FolderNameFull.Length - 1);
            }

            // Directory
            Directory = FolderNameFull;
            if (Directory.IndexOf('\\') > -1)
            {
                Directory = Directory.Substring(0, Directory.LastIndexOf(@"\"));
            }

            // FolderName
            this.foldername = FolderNameFull.Substring(Directory.Length);
            this.foldername = this.foldername.Replace(@"\", string.Empty);
            this.foldername = this.foldername.Replace("/", string.Empty);
        }

        public void AddFile(string filename)
        {
            Files.Add(new File(filename));
        }
        public void AddFile(string filename, string newFilename)
        {
            Files.Add(new File(filename, newFilename));
        }

        public bool ChangedName()
        {
            return FolderName != NewFolderName && NewFolderName != string.Empty;
        }

        public void ApplyRename()
        {
            SetFolderName(NewFolderName);
            folderRenamed = true;
        }
    }

    public enum EngineResult
    {
        NoResult = 0,
        Success,
        Error,
        InternalError
    }

    public struct SearchEngineOptions
    {
        public bool Recursive;
        public string Directory;
        public string FileMask;
    }

    // SearchEngine
    public class SearchEngine
    {
        public EngineResult Result = EngineResult.NoResult;
        public Messages Messages = new Messages();
        public List<Folder> Folders = new List<Folder>();

        public SearchEngineOptions Options;
        //private QuerySearch QuerySearch = new QuerySearch();


        public SearchEngine()
        {
            Options.Directory = String.Empty;
            Options.FileMask = "*.*";
            Options.Recursive = false;
        }

        public SearchEngine(string dir, string filemask, bool recursive)
            : this()
        {
            Options.Directory = dir;
            Options.FileMask = filemask;
            Options.Recursive = recursive;
        }

        /*public void SetQuery(QuerySearch query)
        {
            QuerySearch = query;
        }*/

        //********************************************************************************
        //   Initialize
        //********************************************************************************
        public List<Folder> Search()
        {
            Result = EngineResult.NoResult;
            Messages.Clear();

            /*if (!ValidateScript())
            {
                return;
            }*/

            // Busca os Arquivos
            try
            {
                SearchFiles(Options.Directory, 0);

                if (FilesCount() > 0)
                {
                    Result = EngineResult.Success;
                }
            }
            catch (System.Exception excpt)
            {
                Messages.AddError(excpt.Message);
                Result = EngineResult.InternalError;
            }

            return Folders;
        }

        //********************************************************************************
        //   ValidateScript
        //********************************************************************************
        private bool ValidateScript()
        {
            bool ret = true;

            if (Options.Directory == String.Empty)
            {
                Messages.AddError("Diretório não foi informado");
                Result = EngineResult.Error;
                ret = false;
            }

            return ret;
        }

        private int FilesCount()
        {
            int filesFound = 0;

            foreach (Folder f in Folders)
            {
                filesFound = +f.Files.Count;
            }

            return filesFound;
        }

        private void SearchFiles(string dir, int deep)
        {
            try
            {

                if (deep == 0)
                {
                    Folders.Add(new Folder(Options.Directory, true));
                    Folders[Folders.Count - 1].Deep = deep;
                    foreach (string f in Directory.GetFiles(Options.Directory, Options.FileMask))
                    {
                        /*if (QuerySearch.CheckQueryInFile(f))
                        {
                            Folders[Folders.Count - 1].AddFile(f);
                        }*/
                    }
                }

                foreach (string d in Directory.GetDirectories(dir))
                {
                    Folders.Add(new Folder(d));
                    Folders[Folders.Count - 1].Deep = deep + 1;

                    if (Options.Recursive)
                    {
                        foreach (string f in Directory.GetFiles(d, Options.FileMask))
                        {
                            /*if (QuerySearch.CheckQueryInFile(f))
                            {
                                Folders[Folders.Count - 1].AddFile(f);
                            }*/
                        }

                        SearchFiles(d, deep + 1);
                    }
                }
            }
            catch (System.Exception excpt)
            {
                Messages.AddInternalError(excpt.Message);
            }
        }
    }
}
